import cv2 as cv
import numpy as np


def template_demo():
    tpl = cv.imread("imgs/test008_template.jpg")
    target = cv.imread("imgs/test008.jpg")
    cv.imshow("template image", tpl)
    cv.imshow("target image", target)
    methods = [cv.TM_SQDIFF_NORMED, cv.TM_CCORR_NORMED, cv.TM_CCOEFF_NORMED]   # 3种模板匹配方法
    # ①TM_SQDIFF是平方差匹配；TM_SQDIFF_NORMED是标准平方差匹配。利用平方差来进行匹配,最好匹配为0.匹配越差,匹配值越大。
    # ②TM_CCORR是相关性匹配；TM_CCORR_NORMED是标准相关性匹配。采用模板和图像间的乘法操作,数越大表示匹配程度较高, 0表示最坏的匹配效果。
    # ③TM_CCOEFF是相关性系数匹配；TM_CCOEFF_NORMED是标准相关性系数匹配。将模版对其均值的相对值与图像对其均值的相关值进行匹配,1表示完美匹配,-1表示糟糕的匹配,0表示没有任何相关性(随机序列)。
    # 总结：随着从简单的测量(平方差)到更复杂的测量(相关系数),我们可获得越来越准确的匹配(同时也意味着越来越大的计算代价)。
    th, tw = tpl.shape[:2]
    for md in methods:
        print(md)
        result = cv.matchTemplate(target, tpl, md)
        # 第一个参数image表示待搜索源图像，必须是8位整数或32位浮点。
        # 第二个参数temple表示模板图像，必须不大于源图像并具有相同的数据类型。
        # 第三个参数method表示计算匹配程度的方法。
        min_val, max_val, min_loc, max_loc = cv.minMaxLoc(result)
        # 在给定的矩阵中寻找最大和最小值，并给出它们的位置。 该功能不适用于多通道阵列。 如果您需要在所有通道中查找最小或最大元素，要先将阵列重新解释为单通道。
        if md == cv.TM_SQDIFF_NORMED:
            tl = min_loc
        else:
            tl = max_loc
        br = (tl[0]+tw, tl[1]+th)   # br是矩形右下角的点的坐标
        cv.rectangle(target, tl, br, (0, 0, 255), 2)  # 绘制矩形
        # 参数img表示源图像。
        # 参数pt1表示矩形的一个顶点。
        # 参数pt2表示与pt1相对的对角线上的另一个顶点 。
        # color参数表示矩形线条颜色 (RGB) 或亮度（灰度图像 ）。
        # thickness参数表示组成矩形的线条的粗细程度。取负值时（如 CV_FILLED）函数绘制填充了色彩的矩形。
        # lineType参数表示线条的类型。（此处省略）
        # shift参数表示坐标点的小数点位数。（此处省略）
        cv.imshow("match-" + np.str(md), target)


template_demo()
cv.waitKey(0)
cv.destroyAllWindows()
